package ac.leedsmet.devmanager.core;

import java.io.Serializable;
import java.util.LinkedList;
import java.util.List;

/**
 * Project can only be created via ProjectManagerImpl class.
 *<pre>
 *     ProjectManagerImpl projectManager = new ProjectManagerImpl();
 *     projectManager.createProject("Project Name");
 *</pre>
 * @author Samael
 * @author Takamura
 * @version 1.0
 * @see ProjectManagerImpl#createProject(String)
 */
public class Project implements Serializable {
    /**
	 * Each time the Project class is instantiated it will be given a unique Id
	 */
    private long projectId;

    /**
	 * The Project name does not have to be unique but it must be set when creating a Project object
	 */
    private String name;

    /**
	 * When a Story object is created via StoryManagerImpl class it will be added to the project's list of stories
     * @see StoryManagerImpl
	 */
    private List<Story> stories = new LinkedList();

    /**
	 * When an Issue is created via IssueManagerImpl class it will be added to the project's list of issues
     * @see IssueManagerImpl
	 */
    private List<Issue> issues = new LinkedList();

    /**
     * The Project constructor should not be called directly. Use the ProjectManagerImpl to create a Project.
     * @param name Name of the project
     * @param projectId Auto incremented and unique ID
     */
    protected Project(String name, long projectId) {
        this.name = name;
        this.projectId = projectId;
        new StoryManagerImpl(this);
        new IssueManagerImpl(this) ;
    }

    /**
     *
     * @return Returns the unique Project ID for this Project object.
     */
    public long getProjectId() {
        return projectId;
    }

    /**
     * @return Name of the project
     */
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    /**
     * @return List<Story> Returns all stories for this project whether active or not
     */
    public List<Story> getStories() {
        return stories;
    }

    /**
     * Passing this method a boolean value of true will result in active stories being returned.
     * Setting the boolean to false will return only inactive stories.
     * @return List<Story> Returns stories that are either active or not active, depending on boolean parameter.
     */
    public List<Story> getStories(boolean returnActiveStories) {
        List<Story> filteredList = new LinkedList();
        for (Story story : stories) {
            if (story.isActive() == returnActiveStories) {
                filteredList.add(story);
            }
        }
        return filteredList;
    }

    protected boolean addStory(Story story) {
        return this.stories.add(story);
    }

    /**
     * @return List<Issue> Returns all issues for this project whether active or not
     */
    public List<Issue> getIssues() {
        return issues;
    }

    /**
     * Passing this method a boolean value of true will result in active issues being returned.
     * Setting the boolean to false will return only inactive issues.
     * @return List<Issue> Returns issues that are either active or not active, depending on boolean parameter.
     */
    public List<Issue> getIssues(boolean returnActiveIssues) {
        List<Issue> filteredList = new LinkedList();
        for (Issue issue : issues) {
            if (issue.isActive() == returnActiveIssues) {
                filteredList.add(issue);
            }
        }
        return filteredList;
    }

    protected boolean addIssue(Issue issue) {
        return this.issues.add(issue);
    }

    /**
     * If there are stories and the selected story ID is not 0 then the method swaps the story with the
     * selected ID with the story that has ID==(selected ID) - 1
     * @param story the selected story that needs to be moved
     */
    public void moveUp(Story story) {
        if (!stories.isEmpty()) {
            if(stories.indexOf(story) == 0)
                return;

            int i = stories.indexOf(story);
            java.util.Collections.swap(stories, i, i -1 );
        }
    }

    /**
     * If there are stories and  (selected story ID) != stories.size then swaps the story with the selected ID with the
     * story that has ID==(selected ID) + 1
     * @param story the selected story that needs to be moved
     */
    public void moveDown(Story story) {
        if (!stories.isEmpty()) {
            if(stories.indexOf(story) == stories.size() )
                return;

            int i = stories.indexOf(story);
            java.util.Collections.swap(stories, i, i +1 );
        }
    }

    /**
     * If there are issues and the selected issue ID is not 0 then the method swaps the issue with the
     * selected ID with the issue that has ID==(selected ID) - 1
     * @param issue the selected issue that needs to be moved
     */
    public void moveUp(Issue issue) {
        if (!issues.isEmpty()) {
            if(issues.indexOf(issue) == 0)
                return;

            int i = issues.indexOf(issue);
            java.util.Collections.swap(issues, i, i -1 );
        }
    }

    /**
     * If there are issues and  (selected issue ID) != issues.size then swaps the issue with the selected ID with the
     * issue that has ID==(selected ID) + 1
     * @param issue the selected issue that needs to be moved
     */
    public void moveDown(Issue issue) {
        if (!issues.isEmpty()) {
            if(issues.indexOf(issue) == issues.size())
                return;

            int i = issues.indexOf(issue);
            java.util.Collections.swap(issues, i, i +1 );
        }
    }
}
